﻿
Imports System.Runtime.CompilerServices
Imports osi.root.lock
Imports osi.root.connector
Imports osi.root.formation
Imports osi.root.procedure
Imports osi.root.utils

Public Interface idevice_pool
    Event closing()
    Function max_count() As UInt32
    Function identity() As String
    Function total_count() As UInt32
    Function free_count() As UInt32
    Function expired() As Boolean
    Sub close()
End Interface

Public Interface idevice_pool(Of T)
    Inherits idevice_pool
    Function release(ByVal c As T) As Boolean
End Interface

Public Interface isync_device_pool(Of T)
    Inherits idevice_pool(Of T)
    Function sync_get(ByRef o As T) As Boolean
End Interface

Public Interface iasync_device_pool(Of T)
    Inherits idevice_pool(Of T)
    Function [get](ByVal o As pointer(Of T)) As event_comb
End Interface

Public Interface new_device_event_device_pool
    Event new_device_inserted()
End Interface

Public Interface new_device_event_isync_device_pool(Of T)
    Inherits isync_device_pool(Of T), new_device_event_device_pool
End Interface

Public Module _device_pool
    <Extension()> Public Function limited_max_count(ByVal d As idevice_pool) As Boolean
        assert(Not d Is Nothing)
        Return d.max_count() > 0
    End Function

    <Extension()> Public Function [get](Of T)(ByVal d As idevice_pool, ByRef o As T) As Boolean
        Dim sd As isync_device_pool(Of T) = Nothing
        Return cast(Of isync_device_pool(Of T))(d, sd) AndAlso
               sd.get(o)
    End Function

    <Extension()> Public Function [get](Of T)(ByVal d As idevice_pool(Of T),
                                              ByVal r As pointer(Of T),
                                              ByVal timeout_ms As Int64) As event_comb
        Dim ec As event_comb = Nothing
        Return New event_comb(Function() As Boolean
                                  If d Is Nothing Then
                                      Return False
                                  Else
                                      Dim sd As isync_device_pool(Of T) = Nothing
                                      Dim ad As iasync_device_pool(Of T) = Nothing
                                      If cast(Of isync_device_pool(Of T))(d, sd) Then
                                          ec = sd.get(r, timeout_ms)
                                      ElseIf cast(Of iasync_device_pool(Of T))(d, ad) Then
                                          ec = ad.get(r, timeout_ms)
                                      Else
                                          Return False
                                      End If
                                      assert(Not ec Is Nothing)
                                      Return waitfor(ec) AndAlso
                                             goto_next()
                                  End If
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         goto_end()
                              End Function)
    End Function

    <Extension()> Public Function [get](Of T)(ByVal d As idevice_pool,
                                              ByVal r As pointer(Of T),
                                              ByVal timeout_ms As Int64) As event_comb
        Dim ec As event_comb = Nothing
        Return New event_comb(Function() As Boolean
                                  Dim p As idevice_pool(Of T) = Nothing
                                  If Not d Is Nothing AndAlso
                                     cast(Of idevice_pool(Of T))(d, p) Then
                                      ec = p.get(r, timeout_ms)
                                      Return waitfor(ec) AndAlso
                                             goto_next()
                                  Else
                                      Return False
                                  End If
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         goto_end()
                              End Function)
    End Function

    <Extension()> Public Function release(Of T)(ByVal d As idevice_pool, ByVal c As T) As Boolean
        Dim p As idevice_pool(Of T) = Nothing
        Return cast(Of idevice_pool(Of T))(d, p) AndAlso
               p.release(c)
    End Function

    <Extension()> Public Function [get](Of T)(ByVal d As isync_device_pool(Of T),
                                              ByVal r As pointer(Of T),
                                              ByVal timeout_ms As Int64) As event_comb
        Return sync_get(d, r, timeout_ms)
    End Function

    <Extension()> Public Function [get](Of T)(ByVal d As iasync_device_pool(Of T),
                                              ByVal r As pointer(Of T),
                                              ByVal timeout_ms As Int64) As event_comb
        Dim p As pending_io_punishment = Nothing
        Dim ec As event_comb = Nothing
        Return New event_comb(Function() As Boolean
                                  If d Is Nothing Then
                                      Return False
                                  Else
                                      p = New pending_io_punishment(timeout_ms)
                                      Return goto_next()
                                  End If
                              End Function,
                              Function() As Boolean
                                  ec = d.[get](r)
                                  Return waitfor(ec) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  If ec.end_result() Then
                                      Return goto_end()
                                  Else
                                      ec = p(False)
                                      Return waitfor(ec) AndAlso
                                             goto_prev()
                                  End If
                              End Function)
    End Function

    <Extension()> Public Function sync_get(Of T)(ByVal d As isync_device_pool(Of T),
                                                 ByVal r As pointer(Of T),
                                                 ByVal timeout_ms As Int64) As event_comb
        Dim p As pending_io_punishment = Nothing
        Dim ec As event_comb = Nothing
        Return New event_comb(Function() As Boolean
                                  If d Is Nothing Then
                                      Return False
                                  Else
                                      p = New pending_io_punishment(timeout_ms)
                                      Return goto_next()
                                  End If
                              End Function,
                              Function() As Boolean
                                  If ec.end_result_or_null() Then
                                      Dim x As T = Nothing
                                      If d.sync_get(x) Then
                                          Return eva(r, x) AndAlso
                                                 goto_end()
                                      Else
                                          ec = p(False)
                                          Return waitfor(ec)
                                      End If
                                  Else
                                      Return False
                                  End If
                              End Function)
    End Function
    <Extension()> Public Function get_all(Of T)(ByVal this As new_device_event_isync_device_pool(Of T),
                                                ByVal v As Action(Of T, new_device_event_isync_device_pool(Of T)),
                                                Optional ByVal stopping As Func(Of Boolean) = Nothing) As Boolean
        If v Is Nothing Then
            Return False
        Else
            Return this.get_all(Sub(c As T)
                                    v(c, this)
                                End Sub,
                                stopping)
        End If
    End Function

    <Extension()> Public Function get_all(Of T)(ByVal this As new_device_event_isync_device_pool(Of T),
                                                ByVal v As Action(Of T, new_device_event_isync_device_pool(Of T)),
                                                ByVal stopping As wrapper(Of singleentry)) As Boolean
        Return this.get_all(v, AddressOf stopping.not_null_and_in_use)
    End Function

    <Extension()> Public Function get_all(Of T)(ByVal this As new_device_event_isync_device_pool(Of T),
                                                ByVal v As Action(Of T),
                                                Optional ByVal stopping As Func(Of Boolean) = Nothing) As Boolean
        If this Is Nothing OrElse
           v Is Nothing Then
            Return False
        Else
            Dim h As new_device_event_isync_device_pool(Of T).new_device_insertedEventHandler =
                Sub()
                    If stopping Is Nothing OrElse
                       Not stopping() Then
                        Dim c As T = Nothing
                        While this.sync_get(c)
                            v(c)
                        End While
                    Else
                        RemoveHandler this.new_device_inserted, h
                    End If
                End Sub
            AddHandler this.new_device_inserted, h
            h()
            Return True
        End If
    End Function

    <Extension()> Public Function get_all(Of T)(ByVal this As new_device_event_isync_device_pool(Of T),
                                                ByVal v As Action(Of T),
                                                ByVal stopping As wrapper(Of singleentry)) As Boolean
        Return this.get_all(v, AddressOf stopping.not_null_and_in_use)
    End Function

    <Extension()> Public Function get_all(Of T)(ByVal this As new_device_event_isync_device_pool(Of T),
                                                ByVal v As Func(Of T, new_device_event_isync_device_pool(Of T), event_comb),
                                                Optional ByVal stopping As Func(Of Boolean) = Nothing) As Boolean
        If v Is Nothing Then
            Return False
        Else
            Return this.get_all(Function(c As T) As event_comb
                                    Return v(c, this)
                                End Function,
                                stopping)
        End If
    End Function

    <Extension()> Public Function get_all(Of T)(ByVal this As new_device_event_isync_device_pool(Of T),
                                                ByVal v As Func(Of T, new_device_event_isync_device_pool(Of T), event_comb),
                                                ByVal stopping As wrapper(Of singleentry)) As Boolean
        Return this.get_all(v, AddressOf stopping.not_null_and_in_use)
    End Function

    <Extension()> Public Function get_all(Of T)(ByVal this As new_device_event_isync_device_pool(Of T),
                                                ByVal v As Func(Of T, event_comb),
                                                Optional ByVal stopping As Func(Of Boolean) = Nothing) As Boolean
        If v Is Nothing Then
            Return False
        Else
            Return this.get_all(Sub(c As T)
                                    Dim ec As event_comb = Nothing
                                    assert_begin(New event_comb(Function() As Boolean
                                                                    ec = v(c)
                                                                    Return waitfor(ec) AndAlso
                                                                           goto_next()
                                                                End Function,
                                                                Function() As Boolean
                                                                    Return this.release(c) AndAlso
                                                                           goto_end()
                                                                End Function))
                                End Sub,
                                stopping)
        End If
    End Function

    <Extension()> Public Function get_all(Of T)(ByVal this As new_device_event_isync_device_pool(Of T),
                                                ByVal v As Func(Of T, event_comb),
                                                ByVal stopping As wrapper(Of singleentry)) As Boolean
        Return this.get_all(v, AddressOf stopping.not_null_and_in_use)
    End Function
End Module
